local brain = require("brains/bboy_piggy_hibrain")

local assets = {
    Asset("ANIM", "anim/bboy_piggy_hi.zip"),
}

local prefabs = {}

local FORGETABLE_RECIPES = {} -- 没有设置限制标记（limit flag）的配方在重置（reroll）时会被遗忘。

-- limit 表示,最多不超过这个数量, min 和 max 表示补充商品的数量区间
local WARES = {
    STARTER = { -- 说明（JBK）：这是在新世界开始时，除了随机生成内容之外，给予商人的初始商品。
        {
            ["bboy_nether_moth"] = { recipe = "bboy_piggy_hi_shop_bboy_nether_moth", min = 5, max = 5, limit = 5, },
        },
    },
    ALWAYS = { -- 请确保此表中至少有一笔交易的 min = 1。
        {
            ["bboy_lucky_cat_blueprint"] = { recipe = "bboy_lucky_cat_blueprint", min = 1, max = 1, limit = 1, },
        },
        {
            ["bboy_paper_effigy_item_bboy_zhongyuan_blueprint"] = { recipe = "bboy_piggy_hi_shop_bboy_paper_effigy_item_bboy_zhongyuan_blueprint", min = 1, max = 1, limit = 1, },
        },
        {
            ["bboy_paper_beefalo_item_bboy_zhongyuan_blueprint"] = { recipe = "bboy_piggy_hi_shop_bboy_paper_beefalo_item_bboy_zhongyuan_blueprint", min = 1, max = 1, limit = 1, },
        },
        {
            ["bboy_forsaken_grave_bboy_zhongyuan_blueprint"] = { recipe = "bboy_piggy_hi_shop_bboy_forsaken_grave_bboy_zhongyuan_blueprint", min = 1, max = 1, limit = 1, },
        },
        {
            ["bboy_dry_well_bboy_zhongyuan_blueprint"] = { recipe = "bboy_piggy_hi_shop_bboy_dry_well_bboy_zhongyuan_blueprint", min = 1, max = 1, limit = 1, },
        },
        {
            ["wall_bboy_nether_blossom_item_bboy_zhongyuan_blueprint"] = { recipe = "bboy_piggy_hi_shop_wall_bboy_nether_blossom_item_bboy_zhongyuan_blueprint", min = 1, max = 1, limit = 1, },
        },
        {
            ["bboy_book_survival_guide"] = { recipe = "bboy_piggy_hi_shop_bboy_book_survival_guide", min = 1, max = 1, limit = 1, },
        },
    },
    RANDOM_UNCOMMONS = {
        {
            ["charcoal"] = { recipe = "bboy_piggy_hi_shop_charcoal", min = 20, max = 20, limit = 20, },
        },
        {
            ["nitre"] = { recipe = "bboy_piggy_hi_shop_nitre", min = 15, max = 15, },
        },
        {
            ["beeswax"] = { recipe = "bboy_piggy_hi_shop_beeswax", min = 15, max = 15, },
        },
        {
            ["cutreeds"] = { recipe = "bboy_piggy_hi_shop_cutreeds", min = 30, max = 30, },
        },
        {
            ["moonrocknugget"] = { recipe = "bboy_piggy_hi_shop_moonrocknugget", min = 20, max = 20, },
        },
    },
    RANDOM_RARES = {
        {
            ["panflute"] = { recipe = "bboy_piggy_hi_shop_panflute", min = 1, max = 1, },
        },
        {
            ["opalpreciousgem"] = { recipe = "bboy_piggy_hi_shop_opalpreciousgem", min = 1, max = 1, },
        },
    },
    SEASONAL = {
        [SEASONS.AUTUMN] = {
            ["bearger_fur"] = { recipe = "bboy_piggy_hi_shop_bearger_fur", min = 1, max = 2, limit = 2, },
        },
        [SEASONS.WINTER] = {
            ["deerclops_eyeball"] = { recipe = "bboy_piggy_hi_shop_deerclops_eyeball", min = 1, max = 1, limit = 1, },
        },
        [SEASONS.SPRING] = {
            ["goose_feather"] = { recipe = "bboy_piggy_hi_shop_goose_feather", min = 10, max = 10, limit = 10, },
        },
        [SEASONS.SUMMER] = {
            ["townportaltalisman"] = { recipe = "bboy_piggy_hi_shop_townportaltalisman", min = 10, max = 10, limit = 10, },
        }
    }
}

for _, warebucket in pairs(WARES) do
    for _, prefabdata in pairs(warebucket) do
        for prefab, waredata in pairs(prefabdata) do
            if not table.contains(prefabs, prefab) then
                table.insert(prefabs, prefab)
            end
            if not waredata.limit then
                FORGETABLE_RECIPES[waredata.recipe] = true
            end
        end
    end
end

local function DoChatter(inst, name, index, cooldown)
    inst.sg.mem.canchattertimestamp = GetTime() + cooldown
    inst.components.talker:Chatter(name, index, nil, nil, CHATPRIORITIES.NOCHAT)
end
local function CanChatter(inst)
    return inst.sg.mem.canchattertimestamp == nil or (inst.sg.mem.canchattertimestamp < GetTime())
end
local function TryChatter(inst, name, index, cooldown)
    if inst:CanChatter() then
        inst:DoChatter(name, index, cooldown)
    end
end

local function OnTurnOn(inst)
    inst.sg.mem.trading = true
end
local function OnTurnOff(inst)
    inst.sg.mem.trading = nil
end
local function OnActivate(inst)
    local no_stock = not inst:HasStock()
    if no_stock then
        inst:EnablePrototyper(false)
    end
    inst.sg.mem.didtrade = true
    inst:PushEvent("dotrade", { no_stock = no_stock, })
end

local function HasStock(inst)
    return #inst.components.craftingstation:GetRecipes() > 0
end

local function EnablePrototyper(inst, enabled)
    if not enabled then
        inst:RemoveComponent("prototyper")
    elseif inst.components.prototyper == nil then
        local prototyper = inst:AddComponent("prototyper")
        prototyper.onturnon = OnTurnOn
        prototyper.onturnoff = OnTurnOff
        prototyper.onactivate = OnActivate
        prototyper.trees = TUNING.PROTOTYPER_TREES.BBOY_PIGGY_HI_SHOP_ONE
    end
end

local function AddWares(inst, wares)
    local craftingstation = inst.components.craftingstation
    for item, recipedata in pairs(wares) do
        local oldlimit = craftingstation:GetRecipeCraftingLimit(recipedata.recipe) or 0
        local caplimit = recipedata.limit or 255 -- NOTES(JBK): Netvar limit for SetRecipeCraftingLimit.
        local newlimit = math.min(oldlimit + math.random(recipedata.min, recipedata.max), caplimit)
        if newlimit > 0 and newlimit > oldlimit then
            craftingstation:LearnItem(item, recipedata.recipe)
            craftingstation:SetRecipeCraftingLimit(recipedata.recipe, newlimit)
        end
    end
end

local function RerollWares(inst)
    local craftingstation = inst.components.craftingstation -- 制作站组件
    for recipe, _ in pairs(inst.FORGETABLE_RECIPES) do
        craftingstation:ForgetRecipe(recipe)                -- 将该配方从制作表中移除
    end
    -- 加入常驻商品
    for i = 1, #inst.WARES.ALWAYS do
        inst:AddWares(inst.WARES.ALWAYS[i])
    end
    -- 随机加入较为稀有的商品
    for i = 1, #inst.WARES.RANDOM_UNCOMMONS do
        if math.random() < 0.5 then
            inst:AddWares(inst.WARES.RANDOM_UNCOMMONS[i])
        end
    end
    -- 随机加入稀有的商品
    for i = 1, #inst.WARES.RANDOM_RARES do
        if math.random() < 0.05 then
            inst:AddWares(inst.WARES.RANDOM_RARES[i])
        end
    end
    -- 随机加入1种季节商品
    local seasonalwares = inst.WARES.SEASONAL[TheWorld.state.season]
    if seasonalwares then
        inst:AddWares(seasonalwares)
    end
    inst:EnablePrototyper(inst:HasTag("revealed"))
end

local function Initialize(inst)
    inst.inittask = nil
    inst:AddWares(inst.WARES.STARTER[1])
    inst:RerollWares()
end

local function OnTimerDone(inst, data)
    if data then
        if data.name == "leave" then
            inst:DoTaskInTime(3, function() inst.sg:GoToState("leave") end)
            -- 通知世界嗨猪离开
            if TheWorld and TheWorld.components.bboy_piggyhimanager then
                TheWorld.components.bboy_piggyhimanager:OnPiggyLeave()
            end
        end
    end
end

-- 根据当前世界状态，决定是否发光
local function RecalcLightPhase(inst)
    if TheWorld:HasTag("cave") then
        inst.Light:Enable(true)
        inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
    else
        local phase = TheWorld.state.phase
        if phase == "day" then
            inst.Light:Enable(false)
            inst.AnimState:ClearBloomEffectHandle()
        else
            inst.Light:Enable(true)
            inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
        end
    end
end

local function OnSave(inst, data)
end
local function OnLoad(inst, data)
    if inst.inittask ~= nil then
        inst.inittask:Cancel()
        inst.inittask = nil
    end
    inst.islunarhailing = data.islunarhailing
end
local function OnLoadPostPass(inst)
end

local function SetRevealed(inst, revealed)
    if revealed then
        inst:AddTag("revealed")
        inst:EnablePrototyper(inst:HasStock())
    else
        inst:RemoveTag("revealed")
        inst:EnablePrototyper(false)
    end
end

local function OnEntitySleep(inst)
    if inst.HiddenActionFn then
        inst:HiddenActionFn()
    end
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddDynamicShadow()
    inst.entity:AddLight()
    inst.entity:AddNetwork()

    MakeCharacterPhysics(inst, 100, 0.5) -- 角色物理参数设置

    inst.DynamicShadow:SetSize(1, .75)   -- 阴影设置
    inst.Transform:SetFourFaced()        -- 角色有4个面

    inst.AnimState:SetBank("bboy_piggy_hi")
    inst.AnimState:SetBuild("bboy_piggy_hi")
    inst.AnimState:PlayAnimation("idle")
    inst.AnimState:Hide("ARM_normal")

    inst.Light:SetColour(1, 0.5, 0) -- 橙色光
    inst.Light:SetRadius(2)         -- 设置光照范围
    inst.Light:SetFalloff(0.85)     -- 设置光照衰减率
    inst.Light:SetIntensity(0.85)   -- 设置光照强度
    inst.Light:Enable(true)

    -- 讲话组件
    local talker = inst:AddComponent("talker")
    talker.fontsize = 35                                         -- 字体大小
    talker.font = TALKINGFONT                                    -- 字体样式
    talker.offset = Vector3(0, -600, 0)                          -- 位置相对于实体位置偏移
    talker.name_colour = Vector3(130 / 255, 109 / 255, 57 / 255) -- 字体颜色
    talker.chaticon = "npcchatflair_none"                        -- 角色对应icon,我猜测是本地聊天栏左侧的那个
    talker:MakeChatter()                                         -- 网络同步相关,疑似让NPC说出来的话显示在聊天框中

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst.WARES = WARES                           -- 商人可交易物品列表
    inst.FORGETABLE_RECIPES = FORGETABLE_RECIPES -- 可遗忘的商品

    -- 聊天相关
    inst.DoChatter = DoChatter
    inst.CanChatter = CanChatter
    inst.TryChatter = TryChatter

    -- 重载之后的执行函数
    inst.OnLoad = OnLoad
    inst.OnLoadPostPass = OnLoadPostPass

    -- 脱离加载范围之后的相关函数
    inst.HiddenActionFn = nil
    inst.OnEntitySleep = OnEntitySleep

    inst.HasStock = HasStock                 -- 判断是否还有库存
    inst.RerollWares = RerollWares           -- 重置库存
    inst.AddWares = AddWares                 -- 添加库存
    inst.EnablePrototyper = EnablePrototyper -- 激活科技

    inst.SetRevealed = SetRevealed           -- 设定交易开关函数

    inst:AddComponent("craftingstation")

    inst:AddComponent("inspectable")

    local locomotor = inst:AddComponent("locomotor")
    locomotor.walkspeed = 1.5
    locomotor.runspeed = 4

    local timer = inst:AddComponent("timer")
    timer:StartTimer("leave", 1440)
    inst:ListenForEvent("timerdone", OnTimerDone)

    -- 设定大脑和状态表
    inst:SetBrain(brain)
    inst:SetStateGraph("SGbboy_piggy_hi")

    inst.inittask = inst:DoTaskInTime(0, Initialize)

    inst:WatchWorldState("phase", RecalcLightPhase)
    RecalcLightPhase(inst)

    return inst
end

return Prefab("bboy_piggy_hi", fn, assets, prefabs)
